import springIoc.AutoWired;
import springIoc.Service;
import testpackage.controller.Controller;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.Set;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

        System.out.println(Long.MAX_VALUE - System.currentTimeMillis());
        System.out.println((int) (Long.MAX_VALUE - System.currentTimeMillis()));
        Object o = instanceMap.get("testpackage.controller.Controller");
        ((Controller) o).test();

    }

    private static HashMap<String, Class<?>> beanMap = new HashMap<>();
    private static HashMap<String, Object> instanceMap = new HashMap<>();

    private static String projectPath;

    static {
        URL url = Main.class.getResource(".");
        File file = new File(url.getFile());
        projectPath = file.getAbsolutePath();
        try {
            addToBeanMap(file);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        Set<Class> set = beanMap.values().stream().filter(clazz -> clazz.isAnnotationPresent(Service.class)).collect(Collectors.toSet());

        for (Class clazz : set) {
            String id = clazz.getName();
            try {
                instanceMap.put(id, initServiceBean(clazz));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

    }

    @SuppressWarnings("unchecked")
    private static Object initServiceBean(Class clazz) throws IllegalAccessException {
        Object o = null;
        try {
            var conWithNoArgs = clazz.getDeclaredConstructor();
            o = conWithNoArgs.newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }

        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            if (field.isAnnotationPresent(AutoWired.class)) {
                field.setAccessible(true);
                AutoWired annotation = field.getAnnotation(AutoWired.class);
                if (annotation.value().equals("")) {
                    field.set(o, initServiceBean(field.getType()));
                } else {
                    try {
                        field.set(o, initServiceBean(Class.forName(annotation.value())));
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return o;

    }


    private static void addToBeanMap(File file) throws ClassNotFoundException {
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isDirectory()) {
                addToBeanMap(file1);
            } else if (file1.getName().endsWith(".class")) {
                String classPath = file1.getAbsolutePath().replace(projectPath + "\\", "").replace(".class", "").replaceAll("\\\\", ".");
                Class clazz = Class.forName(classPath);
                beanMap.put(classPath, clazz);
            }
        }
    }

}
